// Generated from Fun.g4 by ANTLR 4.0

package grammar;

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNSimulator;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
import org.antlr.v4.runtime.tree.TerminalNode;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class FunParser extends Parser {
    protected static final DFA[] _decisionToDFA;
    protected static final PredictionContextCache _sharedContextCache =
            new PredictionContextCache();
    public static final int
            T__14 = 1, T__13 = 2, T__12 = 3, T__11 = 4, T__10 = 5, T__9 = 6, T__8 = 7, T__7 = 8, T__6 = 9,
            T__5 = 10, T__4 = 11, T__3 = 12, T__2 = 13, T__1 = 14, T__0 = 15, PATH = 16, SIGNATURE = 17,
            LINE_COMMENT = 18, COMMENT = 19, AND = 20, OR = 21, EQUAL = 22, NOT_EQUAL = 23, LESS_OR_EQUAL = 24,
            MORE_OR_EQUAL = 25, LESS = 26, MORE = 27, PLUS = 28, MINUS = 29, MULT = 30, DIV = 31,
            MOD = 32, LITERAL = 33, IDENTIFIER = 34, WS = 35;
    public static final String[] tokenNames = {
            "<INVALID>", "'->'", "'()'", "'in'", "'.'", "')'", "':'", "'('", "'if'",
            "'fi'", "'='", "'\\'", "'let'", "'then'", "'new'", "'else'", "PATH", "SIGNATURE",
            "LINE_COMMENT", "COMMENT", "'&&'", "'||'", "'=='", "'!='", "'<='", "'=>'",
            "'<'", "'>'", "'+'", "'-'", "'*'", "'/'", "'%'", "LITERAL", "IDENTIFIER",
            "WS"
    };
    public static final int
            RULE_program = 0, RULE_object = 1, RULE_primary = 2, RULE_expression = 3,
            RULE_logicExpression = 4, RULE_compareExpression = 5, RULE_sumExpression = 6,
            RULE_multiplyExpression = 7, RULE_applications = 8, RULE_applicationsList = 9,
            RULE_primaryExpression = 10, RULE_lambda = 11, RULE_ifThenElse = 12, RULE_functionArguments = 13;
    public static final String[] ruleNames = {
            "program", "object", "primary", "expression", "logicExpression", "compareExpression",
            "sumExpression", "multiplyExpression", "applications", "applicationsList",
            "primaryExpression", "lambda", "ifThenElse", "functionArguments"
    };

    @Override
    public String getGrammarFileName() {
        return "Fun.g4";
    }

    @Override
    public String[] getTokenNames() {
        return tokenNames;
    }

    @Override
    public String[] getRuleNames() {
        return ruleNames;
    }

    @Override
    public ATN getATN() {
        return _ATN;
    }


    public FunParser(TokenStream input) {
        super(input);
        _interp = new ParserATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache);
    }

    public static class ProgramContext extends ParserRuleContext {
        public List<ExpressionContext> expression() {
            return getRuleContexts(ExpressionContext.class);
        }

        public ExpressionContext expression(int i) {
            return getRuleContext(ExpressionContext.class, i);
        }

        public TerminalNode EOF() {
            return getToken(FunParser.EOF, 0);
        }

        public ProgramContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_program;
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterProgram(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitProgram(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitProgram(this);
            else return visitor.visitChildren(this);
        }
    }

    public final ProgramContext program() throws RecognitionException {
        ProgramContext _localctx = new ProgramContext(_ctx, getState());
        enterRule(_localctx, 0, RULE_program);
        int _la;
        try {
            enterOuterAlt(_localctx, 1);
            {
                setState(29);
                _errHandler.sync(this);
                _la = _input.LA(1);
                do {
                    {
                        {
                            setState(28);
                            expression();
                        }
                    }
                    setState(31);
                    _errHandler.sync(this);
                    _la = _input.LA(1);
                }
                while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << 7) | (1L << 8) | (1L << 11) | (1L << 12) | (1L << 14) | (1L << LITERAL) | (1L << IDENTIFIER))) != 0));
                setState(33);
                match(EOF);
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class ObjectContext extends ParserRuleContext {
        public TerminalNode SIGNATURE() {
            return getToken(FunParser.SIGNATURE, 0);
        }

        public TerminalNode PATH() {
            return getToken(FunParser.PATH, 0);
        }

        public ObjectContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_object;
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterObject(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitObject(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitObject(this);
            else return visitor.visitChildren(this);
        }
    }

    public final ObjectContext object() throws RecognitionException {
        ObjectContext _localctx = new ObjectContext(_ctx, getState());
        enterRule(_localctx, 2, RULE_object);
        try {
            enterOuterAlt(_localctx, 1);
            {
                setState(35);
                match(PATH);
                setState(36);
                match(SIGNATURE);
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class PrimaryContext extends ParserRuleContext {
        public PrimaryContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_primary;
        }

        public PrimaryContext() {
        }

        public void copyFrom(PrimaryContext ctx) {
            super.copyFrom(ctx);
        }
    }

    public static class MethodCallContext extends PrimaryContext {
        public ExpressionContext expression() {
            return getRuleContext(ExpressionContext.class, 0);
        }

        public TerminalNode PATH() {
            return getToken(FunParser.PATH, 0);
        }

        public ObjectContext object() {
            return getRuleContext(ObjectContext.class, 0);
        }

        public MethodCallContext(PrimaryContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterMethodCall(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitMethodCall(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitMethodCall(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class ExpressionInBracketsContext extends PrimaryContext {
        public ExpressionContext expression() {
            return getRuleContext(ExpressionContext.class, 0);
        }

        public ExpressionInBracketsContext(PrimaryContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterExpressionInBrackets(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitExpressionInBrackets(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor)
                return ((FunVisitor<? extends T>) visitor).visitExpressionInBrackets(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class IfThenElseExpressionContext extends PrimaryContext {
        public IfThenElseContext ifThenElse() {
            return getRuleContext(IfThenElseContext.class, 0);
        }

        public IfThenElseExpressionContext(PrimaryContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterIfThenElseExpression(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitIfThenElseExpression(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor)
                return ((FunVisitor<? extends T>) visitor).visitIfThenElseExpression(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class LambdaExpressionContext extends PrimaryContext {
        public LambdaContext lambda() {
            return getRuleContext(LambdaContext.class, 0);
        }

        public LambdaExpressionContext(PrimaryContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterLambdaExpression(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitLambdaExpression(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitLambdaExpression(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class NewClassContext extends PrimaryContext {
        public ObjectContext object() {
            return getRuleContext(ObjectContext.class, 0);
        }

        public NewClassContext(PrimaryContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterNewClass(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitNewClass(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitNewClass(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class IdentifierContext extends PrimaryContext {
        public TerminalNode IDENTIFIER() {
            return getToken(FunParser.IDENTIFIER, 0);
        }

        public IdentifierContext(PrimaryContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterIdentifier(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitIdentifier(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitIdentifier(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class LiteralContext extends PrimaryContext {
        public TerminalNode LITERAL() {
            return getToken(FunParser.LITERAL, 0);
        }

        public LiteralContext(PrimaryContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterLiteral(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitLiteral(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitLiteral(this);
            else return visitor.visitChildren(this);
        }
    }

    public final PrimaryContext primary() throws RecognitionException {
        PrimaryContext _localctx = new PrimaryContext(_ctx, getState());
        enterRule(_localctx, 4, RULE_primary);
        try {
            setState(56);
            switch (getInterpreter().adaptivePredict(_input, 1, _ctx)) {
                case 1:
                    _localctx = new LiteralContext(_localctx);
                    enterOuterAlt(_localctx, 1);
                {
                    setState(38);
                    match(LITERAL);
                }
                break;

                case 2:
                    _localctx = new IdentifierContext(_localctx);
                    enterOuterAlt(_localctx, 2);
                {
                    setState(39);
                    match(IDENTIFIER);
                }
                break;

                case 3:
                    _localctx = new ExpressionInBracketsContext(_localctx);
                    enterOuterAlt(_localctx, 3);
                {
                    setState(40);
                    match(7);
                    setState(41);
                    expression();
                    setState(42);
                    match(5);
                }
                break;

                case 4:
                    _localctx = new LambdaExpressionContext(_localctx);
                    enterOuterAlt(_localctx, 4);
                {
                    setState(44);
                    lambda();
                }
                break;

                case 5:
                    _localctx = new IfThenElseExpressionContext(_localctx);
                    enterOuterAlt(_localctx, 5);
                {
                    setState(45);
                    ifThenElse();
                }
                break;

                case 6:
                    _localctx = new NewClassContext(_localctx);
                    enterOuterAlt(_localctx, 6);
                {
                    setState(46);
                    match(14);
                    setState(47);
                    object();
                }
                break;

                case 7:
                    _localctx = new MethodCallContext(_localctx);
                    enterOuterAlt(_localctx, 7);
                {
                    setState(48);
                    match(7);
                    setState(49);
                    expression();
                    setState(50);
                    match(5);
                    setState(51);
                    match(6);
                    setState(52);
                    match(PATH);
                    setState(53);
                    match(4);
                    setState(54);
                    object();
                }
                break;
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class ExpressionContext extends ParserRuleContext {
        public ExpressionContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_expression;
        }

        public ExpressionContext() {
        }

        public void copyFrom(ExpressionContext ctx) {
            super.copyFrom(ctx);
        }
    }

    public static class LetContext extends ExpressionContext {
        public ExpressionContext expression() {
            return getRuleContext(ExpressionContext.class, 0);
        }

        public LambdaContext lambda() {
            return getRuleContext(LambdaContext.class, 0);
        }

        public TerminalNode IDENTIFIER() {
            return getToken(FunParser.IDENTIFIER, 0);
        }

        public LetContext(ExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterLet(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitLet(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitLet(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class ThrowLogicExpressionContext extends ExpressionContext {
        public LogicExpressionContext logicExpression() {
            return getRuleContext(LogicExpressionContext.class, 0);
        }

        public ThrowLogicExpressionContext(ExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterThrowLogicExpression(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitThrowLogicExpression(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor)
                return ((FunVisitor<? extends T>) visitor).visitThrowLogicExpression(this);
            else return visitor.visitChildren(this);
        }
    }

    public final ExpressionContext expression() throws RecognitionException {
        ExpressionContext _localctx = new ExpressionContext(_ctx, getState());
        enterRule(_localctx, 6, RULE_expression);
        try {
            setState(66);
            switch (_input.LA(1)) {
                case 12:
                    _localctx = new LetContext(_localctx);
                    enterOuterAlt(_localctx, 1);
                {
                    setState(58);
                    match(12);
                    setState(59);
                    match(IDENTIFIER);
                    setState(60);
                    match(10);
                    setState(61);
                    lambda();
                    setState(62);
                    match(3);
                    setState(63);
                    expression();
                }
                break;
                case 7:
                case 8:
                case 11:
                case 14:
                case LITERAL:
                case IDENTIFIER:
                    _localctx = new ThrowLogicExpressionContext(_localctx);
                    enterOuterAlt(_localctx, 2);
                {
                    setState(65);
                    logicExpression();
                }
                break;
                default:
                    throw new NoViableAltException(this);
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class LogicExpressionContext extends ParserRuleContext {
        public LogicExpressionContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_logicExpression;
        }

        public LogicExpressionContext() {
        }

        public void copyFrom(LogicExpressionContext ctx) {
            super.copyFrom(ctx);
        }
    }

    public static class ThrowCompareExpressionContext extends LogicExpressionContext {
        public CompareExpressionContext compareExpression() {
            return getRuleContext(CompareExpressionContext.class, 0);
        }

        public ThrowCompareExpressionContext(LogicExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterThrowCompareExpression(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitThrowCompareExpression(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor)
                return ((FunVisitor<? extends T>) visitor).visitThrowCompareExpression(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class LogicContext extends LogicExpressionContext {
        public Token operator;

        public ExpressionContext expression() {
            return getRuleContext(ExpressionContext.class, 0);
        }

        public CompareExpressionContext compareExpression() {
            return getRuleContext(CompareExpressionContext.class, 0);
        }

        public TerminalNode AND() {
            return getToken(FunParser.AND, 0);
        }

        public TerminalNode OR() {
            return getToken(FunParser.OR, 0);
        }

        public LogicContext(LogicExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterLogic(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitLogic(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitLogic(this);
            else return visitor.visitChildren(this);
        }
    }

    public final LogicExpressionContext logicExpression() throws RecognitionException {
        LogicExpressionContext _localctx = new LogicExpressionContext(_ctx, getState());
        enterRule(_localctx, 8, RULE_logicExpression);
        int _la;
        try {
            setState(73);
            switch (getInterpreter().adaptivePredict(_input, 3, _ctx)) {
                case 1:
                    _localctx = new LogicContext(_localctx);
                    enterOuterAlt(_localctx, 1);
                {
                    setState(68);
                    compareExpression();
                    setState(69);
                    ((LogicContext) _localctx).operator = _input.LT(1);
                    _la = _input.LA(1);
                    if (!(_la == AND || _la == OR)) {
                        ((LogicContext) _localctx).operator = (Token) _errHandler.recoverInline(this);
                    }
                    consume();
                    setState(70);
                    expression();
                }
                break;

                case 2:
                    _localctx = new ThrowCompareExpressionContext(_localctx);
                    enterOuterAlt(_localctx, 2);
                {
                    setState(72);
                    compareExpression();
                }
                break;
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class CompareExpressionContext extends ParserRuleContext {
        public CompareExpressionContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_compareExpression;
        }

        public CompareExpressionContext() {
        }

        public void copyFrom(CompareExpressionContext ctx) {
            super.copyFrom(ctx);
        }
    }

    public static class CompareContext extends CompareExpressionContext {
        public Token operator;

        public TerminalNode MORE_OR_EQUAL() {
            return getToken(FunParser.MORE_OR_EQUAL, 0);
        }

        public CompareExpressionContext compareExpression() {
            return getRuleContext(CompareExpressionContext.class, 0);
        }

        public SumExpressionContext sumExpression() {
            return getRuleContext(SumExpressionContext.class, 0);
        }

        public TerminalNode MORE() {
            return getToken(FunParser.MORE, 0);
        }

        public TerminalNode NOT_EQUAL() {
            return getToken(FunParser.NOT_EQUAL, 0);
        }

        public TerminalNode LESS_OR_EQUAL() {
            return getToken(FunParser.LESS_OR_EQUAL, 0);
        }

        public TerminalNode EQUAL() {
            return getToken(FunParser.EQUAL, 0);
        }

        public TerminalNode LESS() {
            return getToken(FunParser.LESS, 0);
        }

        public CompareContext(CompareExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterCompare(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitCompare(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitCompare(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class ThrowSumExpressionContext extends CompareExpressionContext {
        public SumExpressionContext sumExpression() {
            return getRuleContext(SumExpressionContext.class, 0);
        }

        public ThrowSumExpressionContext(CompareExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterThrowSumExpression(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitThrowSumExpression(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitThrowSumExpression(this);
            else return visitor.visitChildren(this);
        }
    }

    public final CompareExpressionContext compareExpression() throws RecognitionException {
        CompareExpressionContext _localctx = new CompareExpressionContext(_ctx, getState());
        enterRule(_localctx, 10, RULE_compareExpression);
        int _la;
        try {
            setState(80);
            switch (getInterpreter().adaptivePredict(_input, 4, _ctx)) {
                case 1:
                    _localctx = new CompareContext(_localctx);
                    enterOuterAlt(_localctx, 1);
                {
                    setState(75);
                    sumExpression(0);
                    setState(76);
                    ((CompareContext) _localctx).operator = _input.LT(1);
                    _la = _input.LA(1);
                    if (!((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << EQUAL) | (1L << NOT_EQUAL) | (1L << LESS_OR_EQUAL) | (1L << MORE_OR_EQUAL) | (1L << LESS) | (1L << MORE))) != 0))) {
                        ((CompareContext) _localctx).operator = (Token) _errHandler.recoverInline(this);
                    }
                    consume();
                    setState(77);
                    compareExpression();
                }
                break;

                case 2:
                    _localctx = new ThrowSumExpressionContext(_localctx);
                    enterOuterAlt(_localctx, 2);
                {
                    setState(79);
                    sumExpression(0);
                }
                break;
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class SumExpressionContext extends ParserRuleContext {
        public int _p;

        public SumExpressionContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        public SumExpressionContext(ParserRuleContext parent, int invokingState, int _p) {
            super(parent, invokingState);
            this._p = _p;
        }

        @Override
        public int getRuleIndex() {
            return RULE_sumExpression;
        }

        public SumExpressionContext() {
        }

        public void copyFrom(SumExpressionContext ctx) {
            super.copyFrom(ctx);
            this._p = ctx._p;
        }
    }

    public static class ThrowMultiplyExpressionContext extends SumExpressionContext {
        public MultiplyExpressionContext multiplyExpression() {
            return getRuleContext(MultiplyExpressionContext.class, 0);
        }

        public ThrowMultiplyExpressionContext(SumExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterThrowMultiplyExpression(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitThrowMultiplyExpression(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor)
                return ((FunVisitor<? extends T>) visitor).visitThrowMultiplyExpression(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class AddSubContext extends SumExpressionContext {
        public Token operator;

        public TerminalNode PLUS() {
            return getToken(FunParser.PLUS, 0);
        }

        public SumExpressionContext sumExpression() {
            return getRuleContext(SumExpressionContext.class, 0);
        }

        public TerminalNode MINUS() {
            return getToken(FunParser.MINUS, 0);
        }

        public MultiplyExpressionContext multiplyExpression() {
            return getRuleContext(MultiplyExpressionContext.class, 0);
        }

        public AddSubContext(SumExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterAddSub(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitAddSub(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitAddSub(this);
            else return visitor.visitChildren(this);
        }
    }

    public final SumExpressionContext sumExpression(int _p) throws RecognitionException {
        ParserRuleContext _parentctx = _ctx;
        int _parentState = getState();
        SumExpressionContext _localctx = new SumExpressionContext(_ctx, _parentState, _p);
        SumExpressionContext _prevctx = _localctx;
        int _startState = 12;
        enterRecursionRule(_localctx, RULE_sumExpression);
        int _la;
        try {
            int _alt;
            enterOuterAlt(_localctx, 1);
            {
                {
                    _localctx = new ThrowMultiplyExpressionContext(_localctx);
                    _ctx = _localctx;
                    _prevctx = _localctx;

                    setState(83);
                    multiplyExpression();
                }
                _ctx.stop = _input.LT(-1);
                setState(90);
                _errHandler.sync(this);
                _alt = getInterpreter().adaptivePredict(_input, 5, _ctx);
                while (_alt != 2 && _alt != -1) {
                    if (_alt == 1) {
                        if (_parseListeners != null) triggerExitRuleEvent();
                        _prevctx = _localctx;
                        {
                            {
                                _localctx = new AddSubContext(new SumExpressionContext(_parentctx, _parentState, _p));
                                pushNewRecursionContext(_localctx, _startState, RULE_sumExpression);
                                setState(85);
                                if (!(2 >= _localctx._p)) throw new FailedPredicateException(this, "2 >= $_p");
                                setState(86);
                                ((AddSubContext) _localctx).operator = _input.LT(1);
                                _la = _input.LA(1);
                                if (!(_la == PLUS || _la == MINUS)) {
                                    ((AddSubContext) _localctx).operator = (Token) _errHandler.recoverInline(this);
                                }
                                consume();
                                setState(87);
                                multiplyExpression();
                            }
                        }
                    }
                    setState(92);
                    _errHandler.sync(this);
                    _alt = getInterpreter().adaptivePredict(_input, 5, _ctx);
                }
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            unrollRecursionContexts(_parentctx);
        }
        return _localctx;
    }

    public static class MultiplyExpressionContext extends ParserRuleContext {
        public MultiplyExpressionContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_multiplyExpression;
        }

        public MultiplyExpressionContext() {
        }

        public void copyFrom(MultiplyExpressionContext ctx) {
            super.copyFrom(ctx);
        }
    }

    public static class MulDivContext extends MultiplyExpressionContext {
        public Token operator;

        public TerminalNode DIV() {
            return getToken(FunParser.DIV, 0);
        }

        public TerminalNode MULT() {
            return getToken(FunParser.MULT, 0);
        }

        public TerminalNode MOD() {
            return getToken(FunParser.MOD, 0);
        }

        public ApplicationsContext applications() {
            return getRuleContext(ApplicationsContext.class, 0);
        }

        public MultiplyExpressionContext multiplyExpression() {
            return getRuleContext(MultiplyExpressionContext.class, 0);
        }

        public MulDivContext(MultiplyExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterMulDiv(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitMulDiv(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitMulDiv(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class ThrowApplicationsContext extends MultiplyExpressionContext {
        public ApplicationsContext applications() {
            return getRuleContext(ApplicationsContext.class, 0);
        }

        public ThrowApplicationsContext(MultiplyExpressionContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterThrowApplications(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitThrowApplications(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitThrowApplications(this);
            else return visitor.visitChildren(this);
        }
    }

    public final MultiplyExpressionContext multiplyExpression() throws RecognitionException {
        MultiplyExpressionContext _localctx = new MultiplyExpressionContext(_ctx, getState());
        enterRule(_localctx, 14, RULE_multiplyExpression);
        int _la;
        try {
            setState(98);
            switch (getInterpreter().adaptivePredict(_input, 6, _ctx)) {
                case 1:
                    _localctx = new MulDivContext(_localctx);
                    enterOuterAlt(_localctx, 1);
                {
                    setState(93);
                    applications();
                    setState(94);
                    ((MulDivContext) _localctx).operator = _input.LT(1);
                    _la = _input.LA(1);
                    if (!((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << MULT) | (1L << DIV) | (1L << MOD))) != 0))) {
                        ((MulDivContext) _localctx).operator = (Token) _errHandler.recoverInline(this);
                    }
                    consume();
                    setState(95);
                    multiplyExpression();
                }
                break;

                case 2:
                    _localctx = new ThrowApplicationsContext(_localctx);
                    enterOuterAlt(_localctx, 2);
                {
                    setState(97);
                    applications();
                }
                break;
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class ApplicationsContext extends ParserRuleContext {
        public ApplicationsListContext applicationsList() {
            return getRuleContext(ApplicationsListContext.class, 0);
        }

        public ApplicationsContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_applications;
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterApplications(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitApplications(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitApplications(this);
            else return visitor.visitChildren(this);
        }
    }

    public final ApplicationsContext applications() throws RecognitionException {
        ApplicationsContext _localctx = new ApplicationsContext(_ctx, getState());
        enterRule(_localctx, 16, RULE_applications);
        try {
            enterOuterAlt(_localctx, 1);
            {
                setState(100);
                applicationsList();
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class ApplicationsListContext extends ParserRuleContext {
        public ApplicationTree application;
        public PrimaryExpressionContext primaryExpression;

        public PrimaryExpressionContext primaryExpression(int i) {
            return getRuleContext(PrimaryExpressionContext.class, i);
        }

        public List<PrimaryExpressionContext> primaryExpression() {
            return getRuleContexts(PrimaryExpressionContext.class);
        }

        public ApplicationsListContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_applicationsList;
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterApplicationsList(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitApplicationsList(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitApplicationsList(this);
            else return visitor.visitChildren(this);
        }
    }

    public final ApplicationsListContext applicationsList() throws RecognitionException {
        ApplicationsListContext _localctx = new ApplicationsListContext(_ctx, getState());
        enterRule(_localctx, 18, RULE_applicationsList);

        ArrayList<PrimaryExpressionContext> app = new ArrayList<PrimaryExpressionContext>();
        ApplicationTree tree = new ApplicationTree();


        try {
            int _alt;
            enterOuterAlt(_localctx, 1);
            {
                setState(105);
                _errHandler.sync(this);
                _alt = getInterpreter().adaptivePredict(_input, 7, _ctx);
                do {
                    switch (_alt) {
                        case 1: {
                            {
                                setState(102);
                                ((ApplicationsListContext) _localctx).primaryExpression = primaryExpression();
                                app.add(((ApplicationsListContext) _localctx).primaryExpression);
                            }
                        }
                        break;
                        default:
                            throw new NoViableAltException(this);
                    }
                    setState(107);
                    _errHandler.sync(this);
                    _alt = getInterpreter().adaptivePredict(_input, 7, _ctx);
                } while (_alt != 2 && _alt != -1);
            }

            if (app.size() == 1) {
                tree.unary = true;
                tree.func = app.get(0);
                //System.err.println("add");

            } else {
                ApplicationTree root = tree;
                ApplicationTree cur = root;
                for (int i = app.size() - 1; i > 0; --i) {
                    cur.func = app.get(i);
                    //  System.err.println("add2");
                    ApplicationTree next = new ApplicationTree();
                    cur.next = next;
                    cur = next;
                }

                cur.func = app.get(0);
                cur.unary = true;

            }
            ((ApplicationsListContext) _localctx).application = tree;


        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class PrimaryExpressionContext extends ParserRuleContext {
        public PrimaryContext primary() {
            return getRuleContext(PrimaryContext.class, 0);
        }

        public PrimaryExpressionContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_primaryExpression;
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterPrimaryExpression(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitPrimaryExpression(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitPrimaryExpression(this);
            else return visitor.visitChildren(this);
        }
    }

    public final PrimaryExpressionContext primaryExpression() throws RecognitionException {
        PrimaryExpressionContext _localctx = new PrimaryExpressionContext(_ctx, getState());
        enterRule(_localctx, 20, RULE_primaryExpression);
        try {
            enterOuterAlt(_localctx, 1);
            {
                setState(109);
                primary();
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class LambdaContext extends ParserRuleContext {
        public LambdaContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_lambda;
        }

        public LambdaContext() {
        }

        public void copyFrom(LambdaContext ctx) {
            super.copyFrom(ctx);
        }
    }

    public static class LambdaWithoutArgumentsContext extends LambdaContext {
        public ExpressionContext expression() {
            return getRuleContext(ExpressionContext.class, 0);
        }

        public LambdaWithoutArgumentsContext(LambdaContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterLambdaWithoutArguments(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitLambdaWithoutArguments(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor)
                return ((FunVisitor<? extends T>) visitor).visitLambdaWithoutArguments(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class LambdaWithArgumentsContext extends LambdaContext {
        public ExpressionContext expression() {
            return getRuleContext(ExpressionContext.class, 0);
        }

        public TerminalNode IDENTIFIER(int i) {
            return getToken(FunParser.IDENTIFIER, i);
        }

        public List<TerminalNode> IDENTIFIER() {
            return getTokens(FunParser.IDENTIFIER);
        }

        public LambdaWithArgumentsContext(LambdaContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterLambdaWithArguments(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitLambdaWithArguments(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor)
                return ((FunVisitor<? extends T>) visitor).visitLambdaWithArguments(this);
            else return visitor.visitChildren(this);
        }
    }

    public static class StaticLambdaObjectContext extends LambdaContext {
        public ExpressionContext expression() {
            return getRuleContext(ExpressionContext.class, 0);
        }

        public ObjectContext object() {
            return getRuleContext(ObjectContext.class, 0);
        }

        public StaticLambdaObjectContext(LambdaContext ctx) {
            copyFrom(ctx);
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterStaticLambdaObject(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitStaticLambdaObject(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitStaticLambdaObject(this);
            else return visitor.visitChildren(this);
        }
    }

    public final LambdaContext lambda() throws RecognitionException {
        LambdaContext _localctx = new LambdaContext(_ctx, getState());
        enterRule(_localctx, 22, RULE_lambda);
        int _la;
        try {
            setState(128);
            switch (getInterpreter().adaptivePredict(_input, 10, _ctx)) {
                case 1:
                    _localctx = new LambdaWithArgumentsContext(_localctx);
                    enterOuterAlt(_localctx, 1);
                {
                    setState(111);
                    match(11);
                    setState(113);
                    _errHandler.sync(this);
                    _la = _input.LA(1);
                    do {
                        {
                            {
                                setState(112);
                                match(IDENTIFIER);
                            }
                        }
                        setState(115);
                        _errHandler.sync(this);
                        _la = _input.LA(1);
                    } while (_la == IDENTIFIER);
                    setState(117);
                    match(1);
                    setState(118);
                    expression();
                }
                break;

                case 2:
                    _localctx = new LambdaWithoutArgumentsContext(_localctx);
                    enterOuterAlt(_localctx, 2);
                {
                    setState(119);
                    match(11);
                    setState(120);
                    match(2);
                    setState(121);
                    match(1);
                    setState(122);
                    expression();
                }
                break;

                case 3:
                    _localctx = new StaticLambdaObjectContext(_localctx);
                    enterOuterAlt(_localctx, 3);
                {
                    setState(123);
                    match(14);
                    setState(124);
                    object();
                    setState(126);
                    switch (getInterpreter().adaptivePredict(_input, 9, _ctx)) {
                        case 1: {
                            setState(125);
                            expression();
                        }
                        break;
                    }
                }
                break;
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class IfThenElseContext extends ParserRuleContext {
        public List<ExpressionContext> expression() {
            return getRuleContexts(ExpressionContext.class);
        }

        public ExpressionContext expression(int i) {
            return getRuleContext(ExpressionContext.class, i);
        }

        public IfThenElseContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_ifThenElse;
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterIfThenElse(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitIfThenElse(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitIfThenElse(this);
            else return visitor.visitChildren(this);
        }
    }

    public final IfThenElseContext ifThenElse() throws RecognitionException {
        IfThenElseContext _localctx = new IfThenElseContext(_ctx, getState());
        enterRule(_localctx, 24, RULE_ifThenElse);
        try {
            enterOuterAlt(_localctx, 1);
            {
                setState(130);
                match(8);
                setState(131);
                expression();
                setState(132);
                match(13);
                setState(133);
                expression();
                setState(134);
                match(15);
                setState(135);
                expression();
                setState(136);
                match(9);
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public static class FunctionArgumentsContext extends ParserRuleContext {
        public List<ExpressionContext> expression() {
            return getRuleContexts(ExpressionContext.class);
        }

        public ExpressionContext expression(int i) {
            return getRuleContext(ExpressionContext.class, i);
        }

        public FunctionArgumentsContext(ParserRuleContext parent, int invokingState) {
            super(parent, invokingState);
        }

        @Override
        public int getRuleIndex() {
            return RULE_functionArguments;
        }

        @Override
        public void enterRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).enterFunctionArguments(this);
        }

        @Override
        public void exitRule(ParseTreeListener listener) {
            if (listener instanceof FunListener) ((FunListener) listener).exitFunctionArguments(this);
        }

        @Override
        public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
            if (visitor instanceof FunVisitor) return ((FunVisitor<? extends T>) visitor).visitFunctionArguments(this);
            else return visitor.visitChildren(this);
        }
    }

    public final FunctionArgumentsContext functionArguments() throws RecognitionException {
        FunctionArgumentsContext _localctx = new FunctionArgumentsContext(_ctx, getState());
        enterRule(_localctx, 26, RULE_functionArguments);
        try {
            int _alt;
            enterOuterAlt(_localctx, 1);
            {
                setState(141);
                _errHandler.sync(this);
                _alt = getInterpreter().adaptivePredict(_input, 11, _ctx);
                while (_alt != 2 && _alt != -1) {
                    if (_alt == 1) {
                        {
                            {
                                setState(138);
                                expression();
                            }
                        }
                    }
                    setState(143);
                    _errHandler.sync(this);
                    _alt = getInterpreter().adaptivePredict(_input, 11, _ctx);
                }
                setState(144);
                expression();
            }
        } catch (RecognitionException re) {
            _localctx.exception = re;
            _errHandler.reportError(this, re);
            _errHandler.recover(this, re);
        } finally {
            exitRule();
        }
        return _localctx;
    }

    public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
        switch (ruleIndex) {
            case 6:
                return sumExpression_sempred((SumExpressionContext) _localctx, predIndex);
        }
        return true;
    }

    private boolean sumExpression_sempred(SumExpressionContext _localctx, int predIndex) {
        switch (predIndex) {
            case 0:
                return 2 >= _localctx._p;
        }
        return true;
    }

    public static final String _serializedATN =
            "\2\3%\u0095\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4" +
                    "\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\3\2\6\2 " +
                    "\n\2\r\2\16\2!\3\2\3\2\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4" +
                    "\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4;\n\4\3\5\3\5\3\5\3\5\3\5\3\5" +
                    "\3\5\3\5\5\5E\n\5\3\6\3\6\3\6\3\6\3\6\5\6L\n\6\3\7\3\7\3\7\3\7\3\7\5\7" +
                    "S\n\7\3\b\3\b\3\b\3\b\3\b\3\b\7\b[\n\b\f\b\16\b^\13\b\3\t\3\t\3\t\3\t" +
                    "\3\t\5\te\n\t\3\n\3\n\3\13\3\13\3\13\6\13l\n\13\r\13\16\13m\3\f\3\f\3" +
                    "\r\3\r\6\rt\n\r\r\r\16\ru\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\5\r\u0081" +
                    "\n\r\5\r\u0083\n\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\7\17\u008e" +
                    "\n\17\f\17\16\17\u0091\13\17\3\17\3\17\3\17\2\20\2\4\6\b\n\f\16\20\22" +
                    "\24\26\30\32\34\2\6\3\26\27\3\30\35\3\36\37\3 \"\u0098\2\37\3\2\2\2\4" +
                    "%\3\2\2\2\6:\3\2\2\2\bD\3\2\2\2\nK\3\2\2\2\fR\3\2\2\2\16T\3\2\2\2\20d" +
                    "\3\2\2\2\22f\3\2\2\2\24k\3\2\2\2\26o\3\2\2\2\30\u0082\3\2\2\2\32\u0084" +
                    "\3\2\2\2\34\u008f\3\2\2\2\36 \5\b\5\2\37\36\3\2\2\2 !\3\2\2\2!\37\3\2" +
                    "\2\2!\"\3\2\2\2\"#\3\2\2\2#$\7\1\2\2$\3\3\2\2\2%&\7\22\2\2&\'\7\23\2\2" +
                    "\'\5\3\2\2\2(;\7#\2\2);\7$\2\2*+\7\t\2\2+,\5\b\5\2,-\7\7\2\2-;\3\2\2\2" +
                    ".;\5\30\r\2/;\5\32\16\2\60\61\7\20\2\2\61;\5\4\3\2\62\63\7\t\2\2\63\64" +
                    "\5\b\5\2\64\65\7\7\2\2\65\66\7\b\2\2\66\67\7\22\2\2\678\7\6\2\289\5\4" +
                    "\3\29;\3\2\2\2:(\3\2\2\2:)\3\2\2\2:*\3\2\2\2:.\3\2\2\2:/\3\2\2\2:\60\3" +
                    "\2\2\2:\62\3\2\2\2;\7\3\2\2\2<=\7\16\2\2=>\7$\2\2>?\7\f\2\2?@\5\30\r\2" +
                    "@A\7\5\2\2AB\5\b\5\2BE\3\2\2\2CE\5\n\6\2D<\3\2\2\2DC\3\2\2\2E\t\3\2\2" +
                    "\2FG\5\f\7\2GH\t\2\2\2HI\5\b\5\2IL\3\2\2\2JL\5\f\7\2KF\3\2\2\2KJ\3\2\2" +
                    "\2L\13\3\2\2\2MN\5\16\b\2NO\t\3\2\2OP\5\f\7\2PS\3\2\2\2QS\5\16\b\2RM\3" +
                    "\2\2\2RQ\3\2\2\2S\r\3\2\2\2TU\b\b\1\2UV\5\20\t\2V\\\3\2\2\2WX\6\b\2\3" +
                    "XY\t\4\2\2Y[\5\20\t\2ZW\3\2\2\2[^\3\2\2\2\\Z\3\2\2\2\\]\3\2\2\2]\17\3" +
                    "\2\2\2^\\\3\2\2\2_`\5\22\n\2`a\t\5\2\2ab\5\20\t\2be\3\2\2\2ce\5\22\n\2" +
                    "d_\3\2\2\2dc\3\2\2\2e\21\3\2\2\2fg\5\24\13\2g\23\3\2\2\2hi\5\26\f\2ij" +
                    "\b\13\1\2jl\3\2\2\2kh\3\2\2\2lm\3\2\2\2mk\3\2\2\2mn\3\2\2\2n\25\3\2\2" +
                    "\2op\5\6\4\2p\27\3\2\2\2qs\7\r\2\2rt\7$\2\2sr\3\2\2\2tu\3\2\2\2us\3\2" +
                    "\2\2uv\3\2\2\2vw\3\2\2\2wx\7\3\2\2x\u0083\5\b\5\2yz\7\r\2\2z{\7\4\2\2" +
                    "{|\7\3\2\2|\u0083\5\b\5\2}~\7\20\2\2~\u0080\5\4\3\2\177\u0081\5\b\5\2" +
                    "\u0080\177\3\2\2\2\u0080\u0081\3\2\2\2\u0081\u0083\3\2\2\2\u0082q\3\2" +
                    "\2\2\u0082y\3\2\2\2\u0082}\3\2\2\2\u0083\31\3\2\2\2\u0084\u0085\7\n\2" +
                    "\2\u0085\u0086\5\b\5\2\u0086\u0087\7\17\2\2\u0087\u0088\5\b\5\2\u0088" +
                    "\u0089\7\21\2\2\u0089\u008a\5\b\5\2\u008a\u008b\7\13\2\2\u008b\33\3\2" +
                    "\2\2\u008c\u008e\5\b\5\2\u008d\u008c\3\2\2\2\u008e\u0091\3\2\2\2\u008f" +
                    "\u008d\3\2\2\2\u008f\u0090\3\2\2\2\u0090\u0092\3\2\2\2\u0091\u008f\3\2" +
                    "\2\2\u0092\u0093\5\b\5\2\u0093\35\3\2\2\2\16!:DKR\\dmu\u0080\u0082\u008f";
    public static final ATN _ATN =
            ATNSimulator.deserialize(_serializedATN.toCharArray());

    static {
        _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
    }
}